Newer
Older
Import / research / 3d-experiments / Procedural Buildings / ProceduralBuildings.cpp
//
//  ProceduralBuildings.cpp
//  Procedural Buildings
//
//  Created by John Ryland on 1/10/17.
//  Copyright © 2017 John Ryland. All rights reserved.
//

#include "../Framework/Framework.h"


DECLARE_PROGRAM_UNIFORMS(TexturedProgram)
  DECLARE_UNIFORM(mat4, modelViewProjectionMatrix)
  DECLARE_UNIFORM(sampler2D, textureId)
DECLARE_PROGRAM_UNIFORMS_END

DECLARE_VERTEX(TexturedVertex)
  DECLARE_ATTRIB(vec3, pos, GL_FALSE)
  DECLARE_ATTRIB(vec3, uv,  GL_FALSE)
DECLARE_VERTEX_END


DECLARE_PROGRAM_UNIFORMS(ScreenQuadProgram)
  DECLARE_UNIFORM(vec2f, invScreen)
  DECLARE_UNIFORM(sampler2D, textureId)
DECLARE_PROGRAM_UNIFORMS_END

DECLARE_ATTRIB_TYPE(vt2i, vec4, int16_t, x, y, u, v)
DECLARE_VERTEX(ScreenQuadVertex)
  DECLARE_ATTRIB(vt2i, posAndTex, GL_FALSE)
DECLARE_VERTEX_END


DECLARE_PROGRAM_UNIFORMS(ScreenLineProgram)
  DECLARE_UNIFORM(vec2f, invScreen)
DECLARE_PROGRAM_UNIFORMS_END

DECLARE_ATTRIB_TYPE(v2i, vec2, int16_t, x, y)
DECLARE_VERTEX(ScreenLineVertex)
  DECLARE_ATTRIB(v2i,   pos, GL_FALSE)
  DECLARE_ATTRIB(col4i, col, GL_TRUE)
DECLARE_VERTEX_END


#include "ProceduralBuildings.h"


const char* s_texturedVertexShader =
R"(
  void main()
  {
    gl_TexCoord[0] = vec4(uv, 1.0);
    gl_Position = modelViewProjectionMatrix * vec4(pos, 1.0);
  }
)";


const char* s_texturedFragmentShader =
R"(
  void main()
  {
    gl_FragColor = texture2D(textureId, gl_TexCoord[0].xy);
  }
)";


ProceduralBuildings::~ProceduralBuildings()
{
  m_demoModelContext.shutdown();
}


void addSizedCube(std::vector<TexturedVertex>& a_vertexArray, float a_x, float a_y, float a_z, float a_width, float a_height, float a_depth)
{
  std::vector<vec3f> vertexes;
  CreateTexturedCube(vertexes);
  a_vertexArray.reserve(a_vertexArray.size() + vertexes.size() / 2);
  bool odd = false;
  vec3f last;
  for (const vec3f& v : vertexes)
  {
    if (odd)
      a_vertexArray.push_back(TexturedVertex{ {a_x + (last.x*a_width), a_y + (last.y*a_height), a_z + (last.z*a_depth)}, {v.x, v.y, v.z} });
    else
      last = v;
    odd = !odd;
  }
}

void ProceduralBuildings::prepare()
{
  OptionsType options;
  m_demoModelContext.setup(s_texturedVertexShader, s_texturedFragmentShader, Medium, options, 1);

  m_demoModelContext.m_vertexArray.m_vertexData.clear();

  addSizedCube(m_demoModelContext.m_vertexArray.m_vertexData, 0.0f, -0.30f, 0.0f,   0.5f, 0.60f, 0.5f);
  addSizedCube(m_demoModelContext.m_vertexArray.m_vertexData, 0.0f,  0.30f, 0.0f,   0.4f, 0.75f, 0.4f);
  addSizedCube(m_demoModelContext.m_vertexArray.m_vertexData, 0.0f,  0.70f, 0.0f,   0.3f, 0.50f, 0.3f);

  m_demoModelContext.update();
  m_demoModelContext.setFlag(clearColor | clearDepth | enableCullFace | enableDepthTest);
  m_demoModelContext.setBackgroundColor(0.0f, 0.0f, 0.0f);

  std::vector<uint8_t> rawImageData;
  std::vector<uint8_t> decodedImageData;
  uint32_t imageW, imageH;
  loadFile("cube-map-test-no-border.png", rawImageData);
  decodePNG(decodedImageData, imageW, imageH, rawImageData.data(), rawImageData.size());
  m_demoModelContext.m_uniforms.m_textureId = 0;
  m_demoModelContext.setTextureData(0, imageW, imageH, decodedImageData.data());
}


void ProceduralBuildings::onResize(const vec2f& a_shape)
{
  Math::makePerspectiveMatrix4x4(m_projectionMatrix, Math::degreesToRadians(45.0f), a_shape.x / a_shape.y, 0.1f, 100.0f);
}


void ProceduralBuildings::update(float a_seconds)
{
  float trans[3] = { 0.0f, 0.0f, -20.0f };
  float rotate[3] = { sin(a_seconds*0.5f) * 35.0f + 20.0f, fmod(a_seconds*47.f, 360.0f), 0.0 };
  float baseModelViewMatrix[16];
  Math::translationRotationScaleToMatrix4x4(baseModelViewMatrix, trans, rotate, 5.0f);

  Math::multiplyMatrix4x4(m_demoModelContext.m_uniforms.m_modelViewProjectionMatrix.m[0], m_projectionMatrix, baseModelViewMatrix);
}


void ProceduralBuildings::draw()
{
  m_demoModelContext.draw();
}


REGISTER_DEMO_CONTEXT("Procedural Buildings", ProceduralBuildings)